#ifndef AGT_SCENE_H
#define AGT_SCENE_H

#define AE_LATEST_SCENE_VERSION 1
#define AE_LATEST_SCENE_REVISION 1

namespace agtk {

/** SceneVersion structure. The first thing writen and read. Must not change to keep backwards compatibility. **/
struct SceneVersion
{
	int version;
	int revision;
};

/** SceneHeader structure. Contains information about the maximum numbers of different assets and weather or not the fog/skybox information needs loading or using. **/
struct SceneHeader
{
	int max_objects;
	int max_lights;
	int max_cameras;
	int max_items;
	int max_entities;
	int max_sounds;

	bool use_skybox;
	bool use_fog;
};

/** Structure containing information about a single side of the skybox. **/
struct SceneSkyboxSide
{
	char* filename;
	char* filepath;
	int texture_id;
};

/** Structure containing information about the whole skybox. **/
struct SceneSkybox
{
	SceneSkyboxSide front;
	SceneSkyboxSide back;
	SceneSkyboxSide left;
	SceneSkyboxSide right;
	SceneSkyboxSide top;
	SceneSkyboxSide bottom;
};

/** Scructure containing fog information. **/
struct SceneFog
{
	int mode;
	float start;
	float end;
	float density;
	Color color;
	SceneFog(void) {
		mode=0;
		start=0;
		end=0;
		density=0;
		color=Color(1.0f, 1.0f, 1.0f, 1.0f);
	}
};

/** Structure containing information about player starting points. **/
struct SceneStartingPosition
{
	Vec3<float> position;
	Vec3<float> angle;
};

/** Structure containing more information about the scene. **/
struct SceneDetail
{
	SceneDetail(void) {
		name = "";
		author = "";
		starting_position.position.Set(0.0f, 0.0f, 0.0f);
		starting_position.angle.Set(0.0f, 0.0f, 0.0f);
	}

	std::string name;
	std::string author;
	SceneStartingPosition starting_position;
};

/** Structure containing information about the scene environment. **/
struct SceneEnvironment
{
	SceneEnvironment(void) {
		gravity = 0;
		sun_direction.Set(0.0f, 0.0f, 0.0f);
		sun_color = Color(1.0f, 1.0f, 1.0f, 1.0f);
		ambient_color = Color(0.3f, 0.3f, 0.3f, 1.0f);
	}

	float gravity;
	Vec3<float> sun_direction;
	Color sun_color;
	Color ambient_color;
};

/** Contains all objects, entities, etc. in the scene. **/
struct SceneContents
{
	SceneContents(void) {
		cameras = new LinkedList<Camera>;
		objects = new LinkedList<SceneObject>;
		//lights = new LinkedList<SceneLight>;
		//items = new LinkedList<SceneItem>;
		//entities = new LinkedList<SceneEntity>;
		//sounds = new LinkedList<SceneSound>;
		
		activeCamera = NULL;
	}

	LinkedList<Camera>* cameras;
	LinkedList<SceneObject>* objects;
	//LinkedList<SceneLight>* lights;
	//LinkedList<SceneItem>* items;
	//LinkedList<SceneEntity>* entities;
	//LinkedList<SceneSound>* sounds;
	
	Camera* activeCamera;
};

/** Class for holding all of the scene's data. **/
class Scene
{
public:
	/** Constructor. **/
	Scene(void);

	/** Destructor. **/
	~Scene(void);

	/** Version object. **/
	SceneVersion m_version;

	/** Header object. **/
	SceneHeader m_header;

	/** Skybox object. **/
	SceneSkybox m_skybox;

	/** Fog data object. **/
	SceneFog m_fog;

	/** Scene detail object. **/
	SceneDetail m_detail;

	/** Scene environment object. **/
	SceneEnvironment m_environment;

	/** Scene contents object. **/
	SceneContents m_contents;

	/** Save the scene to a file. **/
	bool Save(char* filename);

	/** Load scene date from a file. **/
	bool Load(char* filename);

	/** Render the scene. **/
	void Render(void);

	/** Update the scene. **/
	void Update(void);

	/** Add a scene object to the linked list. **/
	bool AddSceneObject(char* name, char* path, bool shared);
	
	/** Add a camera to  the scene. **/
	bool AddCamera(Camera* camera, bool makeActive = false);
	
	/** Get the scene's active camera. **/
	Camera* GetActiveCamera(void);

	/** Has the scene finished being loaded? **/
	bool m_bIsLoaded;
};

}

#endif